package test.synccall;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

/**
 * @Classname TaskController
 * @Description TODO
 * @Date 2022/3/22 9:22
 * @Created by KangJonney
 */

@RestController
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
@RequestMapping("/test/")
public class TaskController {

    private static final Logger log = LoggerFactory.getLogger(TaskController.class);

    //超时结果
    private static final ResponseMsg<String> OUT_OF_TIME_RESULT = new ResponseMsg<>(-1, "超时", "out of time");

    //超时时间
    private static final long OUT_OF_TIME = 3000L;

    @Autowired
    private TaskQueue taskQueue;


    public static void main(String[] args) {
        SpringApplication.run(TaskController.class, args);
    }

    /**
     * 这里我们同样注入了taskQueue。请求方法就只有一个getResult，返回值为DeferredResult<ResponseMsg>。
     * 这里我们首先创建了DeferredResult对象result并且设定超时时间和超时返回结果；随后设定result的onTimeout和onCompletion方法，
     * 其实就是传入两个Runnable对象来实现回调的效果；之后就是加锁并且将result加入任务队列中。
     *
     * @return
     */
    @RequestMapping(value = "/get", method = RequestMethod.GET)
    public DeferredResult<ResponseMsg<String>> getResult() {
        log.info("接收请求，开始出来...");
        //建立DeferredResult对象，设置超时时间，以及超时返回超时结果
        DeferredResult<ResponseMsg<String>> result = new DeferredResult<>(OUT_OF_TIME, OUT_OF_TIME_RESULT);
        result.onTimeout(() -> {
            log.info("超时调用" + result.getResult());
        });
        result.onCompletion(() -> {
            log.info("完成调用" + result.getResult());
        });
        //并发、加锁
        synchronized (taskQueue) {
            taskQueue.put(result);
        }
        log.info("接收任务线程完成并退出！");
        return result;
    }

}
